package com.hjx.windowtool.video.combine;

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;

import java.io.File;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.bytedeco.javacpp.avcodec;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.OpenCVFrameGrabber;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Text;

import com.hjx.windowtool.photo2video.JavacvUtils;
import com.hjx.windowtool.util.StrUtil;

import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;

public class VCombineApp {

	protected Shell shell;
	private Table table;
	private Text text;

	/**
	 * Launch the application.
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			VCombineApp window = new VCombineApp();
			window.open();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Open the window.
	 */
	public void open() {
		Display display = Display.getDefault();
		createContents();
		shell.open();
		shell.layout();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
	}

	/**
	 * Create contents of the window.
	 */
	protected void createContents() {
		shell = new Shell();
		shell.setSize(668, 437);
		shell.setText("合并测试");
		shell.setLayout(new GridLayout(1, false));
		
		table = new Table(shell, SWT.BORDER | SWT.FULL_SELECTION);
		table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		table.setHeaderVisible(true);
		table.setLinesVisible(true);
		
		TableColumn tableColumn = new TableColumn(table, SWT.NONE);
		tableColumn.setWidth(132);
		tableColumn.setText("名称");
		
		Composite composite = new Composite(shell, SWT.NONE);
		composite.setLayout(new GridLayout(7, false));
		GridData gd_composite = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
		gd_composite.widthHint = 159;
		composite.setLayoutData(gd_composite);
		
		Label label = new Label(composite, SWT.NONE);
		label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		label.setText("保存");
		
		text = new Text(composite, SWT.BORDER);
		GridData gd_text = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1);
		gd_text.widthHint = 142;
		text.setLayoutData(gd_text);
		
		Button button_1 = new Button(composite, SWT.NONE);
		button_1.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				FileDialog f = new FileDialog(shell,SWT.MULTI);
				f.setFilterExtensions(new String[] {"*.mp4;*.avi;*.wmv;*.rmvb","*.*"});
				String open = f.open();
				System.out.println(open+"=="+f.getFileNames().length);
				if (open==null) {
					return;
				}
				String parent = new File(open).getParent();
				String[] fileNames = f.getFileNames();
				for (String string : fileNames) {
					System.out.println(string);
					TableItem ti = new TableItem(table, SWT.NONE);
					ti.setText(string);
					ti.setData(new File(parent, string));
				}
				text.setText(parent+"\\combine.mp4");
			}
		});
		button_1.setText("添加");
		
		Button button_4 = new Button(composite, SWT.NONE);
		button_4.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				TableItem[] selection = table.getSelection();
				if (selection==null||selection.length<=0) {
					return;
				}
				for (TableItem tableItem : selection) {
					tableItem.dispose();
				}
			}
		});
		button_4.setText("删除");
		
		Button button_2 = new Button(composite, SWT.NONE);
		button_2.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				moveItem(-1);
			}
		});
		button_2.setText("上移");
		
		Button button_3 = new Button(composite, SWT.NONE);
		button_3.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				moveItem(1);
			}
		});
		button_3.setText("下移");
		
		Button button = new Button(composite, SWT.NONE);
		button.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				final List<String> collect = Stream.of(table.getItems()).map(e1->e1.getData().toString()).collect(Collectors.toList());
				String save = text.getText();
				new Thread(new Runnable() {
					public void run() {
						FFmpegFrameRecorder ffr = null;
						try {
							for (String string : collect) {
								System.out.println(string);
								try(FFmpegFrameGrabber ff = new FFmpegFrameGrabber(string)) {
									ff.start();
									if (ffr == null) {
										ffr = new FFmpegFrameRecorder(save, ff.getImageWidth(), ff.getImageHeight(), ff.getAudioChannels());
//										StrUtil.copy(ff, ffr);
//										ffr.setVideoCodec(avcodec.AV_CODEC_ID_MPEG4);
//										ffr.setFormat("mp4");
//										ffr.setFrameRate(25);
										ffr.setInterleaved(true);

										/**
										 * 该参数用于降低延迟 参考FFMPEG官方文档：https://trac.ffmpeg.org/wiki/StreamingGuide
										 * 官方原文参考：ffmpeg -f dshow -i video="Virtual-Camera" -vcodec libx264 -tune
										 * zerolatency -b 900k -f mpegts udp://10.1.0.102:1234
										 */

										ffr.setVideoOption("tune", "zerolatency");
										/**
										 * 权衡quality(视频质量)和encode speed(编码速度) values(值)： ultrafast(终极快),superfast(超级快),
										 * veryfast(非常快), faster(很快), fast(快), medium(中等), slow(慢), slower(很慢),
										 * veryslow(非常慢)
										 * ultrafast(终极快)提供最少的压缩（低编码器CPU）和最大的视频流大小；而veryslow(非常慢)提供最佳的压缩（高编码器CPU）的同时降低视频流的大小
										 * 参考：https://trac.ffmpeg.org/wiki/Encode/H.264 官方原文参考：-preset ultrafast as the
										 * name implies provides for the fastest possible encoding. If some tradeoff
										 * between quality and encode speed, go for the speed. This might be needed if
										 * you are going to be transcoding multiple streams on one machine.
										 */
										ffr.setVideoOption("preset", "ultrafast");
										/**
										 * 参考转流命令: ffmpeg -i'udp://localhost:5000?fifo_size=1000000&overrun_nonfatal=1'
										 * -crf 30 -preset ultrafast -acodec aac -strict experimental -ar 44100 -ac
										 * 2-b:a 96k -vcodec libx264 -r 25 -b:v 500k -f flv 'rtmp://<wowza
										 * serverIP>/live/cam0' -crf 30
										 * -设置内容速率因子,这是一个x264的动态比特率参数，它能够在复杂场景下(使用不同比特率，即可变比特率)保持视频质量；
										 * 可以设置更低的质量(quality)和比特率(bit rate),参考Encode/H.264 -preset ultrafast
										 * -参考上面preset参数，与视频压缩率(视频大小)和速度有关,需要根据情况平衡两大点：压缩率(视频大小)，编/解码速度 -acodec aac
										 * -设置音频编/解码器 (内部AAC编码) -strict experimental -允许使用一些实验的编解码器(比如上面的内部AAC属于实验编解码器)
										 * -ar 44100 设置音频采样率(audio sample rate) -ac 2 指定双通道音频(即立体声) -b:a 96k 设置音频比特率(bit
										 * rate) -vcodec libx264 设置视频编解码器(codec) -r 25 -设置帧率(frame rate) -b:v 500k
										 * -设置视频比特率(bit rate),比特率越高视频越清晰,视频体积也会变大,需要根据实际选择合理范围 -f flv
										 * -提供输出流封装格式(rtmp协议只支持flv封装格式) 'rtmp://<FMS server IP>/live/cam0'-流媒体服务器地址
										 */
										ffr.setVideoOption("crf", "0");
										// 2000 kb/s, 720P视频的合理比特率范围
										ffr.setVideoBitrate(ff.getVideoBitrate()<=0?JavacvUtils.getDefaultVideoBitrate(ff.getImageHeight()):ff.getVideoBitrate());
										// h264编/解码器
										ffr.setVideoCodec(avcodec.AV_CODEC_ID_MPEG4);
										// 封装格式flv
										ffr.setFormat("mp4");
										// 视频帧率(保证视频质量的情况下最低25，低于25会出现闪屏)
										ffr.setFrameRate(25);
										// 关键帧间隔，一般与帧率相同或者是视频帧率的两倍
										// ffr.setGopSize((int) (FRAME_RATE * 2));
										// 不可变(固定)音频比特率
										ffr.setAudioOption("crf", "0");
										// 最高质量
										ffr.setAudioQuality(0);
										// 音频比特率
										ffr.setAudioBitrate(ff.getAudioBitrate()<=0?192000:ff.getAudioBitrate());
										// 音频采样率
										ffr.setSampleRate(ff.getSampleRate()<=0?44100:ff.getSampleRate());
										// 双通道(立体声)
										ffr.setAudioChannels(2);
										// 音频编/解码器
										ffr.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
										ffr.start();
									}
									System.out.println("开始写入文件");
									Frame grab = null;
									while ((grab = ff.grabFrame()) != null) {
//										System.out.println(grab.timestamp);
										try {
											ffr.setTimestamp(grab.timestamp);
											ffr.record(grab);
										} catch (Exception e) {
											
										}
									}
								}
							}
						} catch (Exception e2) {
							e2.printStackTrace();
						} finally {
							System.out.println("处理完成");
							try {
								if (ffr != null) {
									ffr.close();
								}
							} catch (Exception e2) {
								e2.printStackTrace();
							}
						}
					}
				}).start();
			}
		});
		button.setText("合并");
		
		ProgressBar progressBar = new ProgressBar(shell, SWT.NONE);
		progressBar.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));

	}

	/**
	 * 
	 */
	public void moveItem(int moveSize) {
		TableItem[] selection = table.getSelection();
		if (selection==null||selection.length<=0) {
			return;
		}
		TableItem tableItem = selection[0];
		int selectionIndex = table.getSelectionIndex();
		if (moveSize>0) {
			moveSize+=1;
		}
		int index = selectionIndex+moveSize;
		if (index<0||index>table.getItemCount()) {
			return;
		}
		TableItem tableItem2 = new TableItem(table, SWT.NONE, index);
		tableItem2.setText(tableItem.getText());
		tableItem2.setData(tableItem.getData());
		table.setSelection(index);
		tableItem.dispose();
	}
}
